using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Templates;
using Avalonia.Markup.Xaml;
using Microsoft.Extensions.DependencyInjection;
using welog.Common;
using welog.Features;
using welog.Services;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Loader;
using Avalonia.Input;
using Avalonia.Platform;
using Avalonia.Threading;
using welog.core;
using welog.core.PluginAssemblyManager;
using KeyModifiers = welog.Utilities.KeyModifiers;
namespace welog;

public partial class App : Application
{
    public IServiceProvider? ServiceProvider { get; set; }

    public override void Initialize()
    {
        AvaloniaXamlLoader.Load(this);
        ServiceProvider = ConfigureServices();
    }

    public override void OnFrameworkInitializationCompleted()
    {
        if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
        {
            var viewLocator = ServiceProvider?.GetRequiredService<IDataTemplate>();
            var mainVm = ServiceProvider?.GetRequiredService<MainWindowViewModel>();

            desktop.MainWindow = viewLocator?.Build(mainVm) as Window;
        }
        
        base.OnFrameworkInitializationCompleted();
    }

    private static ServiceProvider ConfigureServices()
    {
        var viewlocator = Current?.DataTemplates.First(x => x is ViewLocator);
        var services = new ServiceCollection();

        if (viewlocator is not null)
            services.AddSingleton(viewlocator);
        services.AddSingleton<PageNavigationService>();
        
        services.AddSingleton<SysConfig>();
        
        AddPlugins(services);

        services.AddSingleton<WelogHandle>();
        
        // Viewmodels
        services.AddSingleton<MainWindowViewModel>();
        
        var types = AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(s => s.GetTypes())
            .Where(p => !p.IsAbstract && typeof(WelogPageBase).IsAssignableFrom(p));
        foreach (var type in types)
            services.AddSingleton(typeof(WelogPageBase), type);

        return services.BuildServiceProvider();
    }

    internal static void AddPlugins(ServiceCollection services)
    {
        var assemplyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugin");
        var assemblyFileList=Directory.GetFiles(assemplyPath);
        
        var assemblyList = new List<Assembly>();
        
        foreach (string s in assemblyFileList)
        {
            var alc = new PluginAssemblyLoadContext(s);
        
            // 加载程序到上下文
            // 注意:路径必须为绝对路径.
            Assembly assembly = alc.LoadFromAssemblyPath(s);
            assemblyList.Add(assembly);
        }
        
        var pluginTypes= assemblyList
            .SelectMany(s => s.GetTypes())
            .Where(p => !p.IsInterface && typeof(IWelogTextPlugin).IsAssignableFrom(p));
        foreach (var pluginType in pluginTypes)
            services.AddSingleton(typeof(IWelogTextPlugin), pluginType);
    }
}

